/*
 *  (C) Copyright 2008 Insula T.I. Ltda.
 * 
 *  This file is part of Vulcano.
 *
 *  Vulcano is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  Vulcano is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with Vulcano.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.openinsula.vulcano.orm.dao.hibernate;

import java.util.ArrayList;
import java.util.List;

import org.openinsula.vulcano.orm.dao.query.spec.AbstractGroupSpec;
import org.openinsula.vulcano.orm.dao.query.spec.AbstractSingleValuePropertySpec;
import org.openinsula.vulcano.orm.dao.query.spec.AndSpec;
import org.openinsula.vulcano.orm.dao.query.spec.BetweenSpec;
import org.openinsula.vulcano.orm.dao.query.spec.EqualsSpec;
import org.openinsula.vulcano.orm.dao.query.spec.GreaterOrEqualSpec;
import org.openinsula.vulcano.orm.dao.query.spec.GreaterSpec;
import org.openinsula.vulcano.orm.dao.query.spec.InSpec;
import org.openinsula.vulcano.orm.dao.query.spec.LesserOrEqualSpec;
import org.openinsula.vulcano.orm.dao.query.spec.LesserSpec;
import org.openinsula.vulcano.orm.dao.query.spec.LikeSpec;
import org.openinsula.vulcano.orm.dao.query.spec.NotEqualsSpec;
import org.openinsula.vulcano.orm.dao.query.spec.NotNullSpec;
import org.openinsula.vulcano.orm.dao.query.spec.NullSpec;
import org.openinsula.vulcano.orm.dao.query.spec.OrSpec;
import org.openinsula.vulcano.orm.dao.query.spec.Spec;
import org.openinsula.vulcano.orm.dao.query.spec.SpecVisitor;

/**
 * @author rebola
 * @author yanaga
 * @since 1.1
 * @see SpecVisitor
 */
public class ParameterSpecVisitor implements SpecVisitor<List<Object>> {

	public List<Object> visit(final AndSpec andSpec) {
		return groupSpecVisit(andSpec);
	}
	
	public List<Object> visit(final OrSpec orSpec) {
		return groupSpecVisit(orSpec);
	}

	public List<Object> visit(final EqualsSpec equalsSpec) {
		return singleValuePropertySpecVisit(equalsSpec);
	}
	
	public List<Object> visit(final NotEqualsSpec notEqualsSpec) {
		return singleValuePropertySpecVisit(notEqualsSpec);
	}

	public List<Object> visit(final GreaterOrEqualSpec greaterOrEqualSpec) {
		return singleValuePropertySpecVisit(greaterOrEqualSpec);
	}

	public List<Object> visit(final GreaterSpec greaterSpec) {
		return singleValuePropertySpecVisit(greaterSpec);
	}

	public List<Object> visit(final LesserOrEqualSpec lesserOrEqualSpec) {
		return singleValuePropertySpecVisit(lesserOrEqualSpec);
	}

	public List<Object> visit(final LesserSpec lesserSpec) {
		return singleValuePropertySpecVisit(lesserSpec);
	}

	public List<Object> visit(final LikeSpec likeSpec) {
		return singleValuePropertySpecVisit(likeSpec);
	}

	public List<Object> visit(final NotNullSpec notNullSpec) {
		return new ArrayList<Object>();
	}

	public List<Object> visit(final NullSpec nullSpec) {
		return new ArrayList<Object>();
	}

	public List<Object> visit(BetweenSpec betweenSpec) {
		List<Object> params = new ArrayList<Object>();
		
		params.add(betweenSpec.getFirstValue());
		params.add(betweenSpec.getSecondValue());
		
		return params;
	}
	
	public List<Object> visit(InSpec inSpec) {
		List<Object> params = new ArrayList<Object>();
		
		params.addAll(inSpec.getValues());
		
		return params;
	}
	
	private List<Object> groupSpecVisit(AbstractGroupSpec spec) {
		List<Object> params = new ArrayList<Object>();
		
		for (Spec s: spec.getExpressions()) {
			params.addAll(s.accept(this));
		}
		
		return params;
	}
	
	private List<Object> singleValuePropertySpecVisit(AbstractSingleValuePropertySpec spec) {
		List<Object> params = new ArrayList<Object>();
		params.add(spec.getValue());
		
		return params;
	}
	
}